var primitiveNow = [];
var materialNow = null;
var oldPositionX = 0;
var oldPositionY = 0;

var mouseDown = false;
var lightPos = [0, 100, 0];

var camera;

function init(){
	QtInit(function(){
		SceneManager.createLoader(function(){
		});
		TextureManager.createLoader(function(){
		});
		camera = SceneManager.createMainCamera();
		camera.setProjection();
		camera.setCamera([10, 10, 0], [0, 5, 0], [0, 1, 0]);
		camera.disable();
		light = SceneManager.createLight("main_light", {
			"type" : "DIRECT",
			"direction" : [0, 400, 80],
			"color" : [1, 1, 1, 1],
			"power" : 1
		});
		light1 = SceneManager.createLight("light1", {
			"type" : "DIRECT",
			"direction" : [0, 1, 0.4],
			"color" : [1, 1, 1, 0.5],
		});
		light2 = SceneManager.createLight("light2", {
			"type" : "POINT",
			"position" : lightPos,
			"color" : [1, 1, 1, 1],
			"attenuation" : 0.01
		});
		
		
		SceneManager.loadModel("Sponza", "media/model/Sponza2.o3dtgz", "main_camera", function(transform){
			//you can not directly bind it to the client root, because the transform tree root of camera's
			//render node is the transform camera
			transform.scale(0.1, 0.1, 0.1);
			SceneManager.listPrimitives();
			
			MaterialManager.loadFxFile("phong", "media/material/phong.json", function(phong){
				var primitives = SceneManager.getTransformPrimitiveMap("Sponza");
				for(var i = 0; i < primitives.length; i++){
					var material = SceneManager.getPrimitive(primitives[i]).material;
					if(isset(material)){
						material = MaterialManager.createFromImportedMaterial(material, "phong");
						SceneManager.getPrimitive(primitives[i]).material = material;
					}else{
						SceneManager.getPrimitive(primitives[i]).material = phong;
					}
				}
				
				var replace = {
					"bricks" : "media/texture/spnza_bricks_a_ddn.jpg",
					"arch" : "media/texture/sponza_arch_ddn.jpg",
					"column_a" : "media/texture/sponza_column_a_ddn.jpg",
					"column_b" : "media/texture/sponza_column_b_ddn.jpg",
					"column_c" : "media/texture/sponza_column_c_ddn.jpg",
					"thorn" : "media/texture/sponza_thorn_ddn.jpg",
					"lion" : "media/texture/lion_ddn.jpg",
					"background" : "media/texture/background_ddn.jpg"
				}
				var opCount = 0;
				for(var materialName in replace){
					var option = MaterialManager.getOption(materialName).Texture.normalSampler;
					option.src = replace[materialName];
					opCount++;
					TextureManager.createSampler(option.src, option, function(sampler){
						opCount--;
						if(opCount == 0){
							for (var materialName in replace) {
								MaterialManager.updateParam(materialName, "hasNormalSampler", 1);
								MaterialManager.updateTexture(materialName, "normalSampler", TextureManager.getSampler(replace[materialName]), replace[materialName]);
//								MaterialManager.updateParam(materialName, "shininess", 0);
							}
						}
					});
				}

//				light.createShadowMap("main_camera");
				
//				light.bindToTransform("Sponza");
				
				SceneManager.createSkybox([1, 1, 1, 1]);
				DeferredShading.createGBuffer("gbuffer", "main_camera");
//				var shadow = DeferredShading.calShadowMap(light);
//				light.shadow = PostProcessing.gaussEdge(light.shadow, 3);
				
				var ssaoMap = DeferredShading.createSSAO();
				
				DeferredShading.addLight(light);
//				DeferredShading.addLight(light1);
				DeferredShading.addLight(light2, true);
				var extract = PostProcessing.extract(DeferredShading.getFinalRenderTarget(), 0.9);
				extract = PostProcessing.gray(extract);
				extract = PostProcessing.gauss(extract, 5);
				PostProcessing.compound(extract, DeferredShading.getFinalRenderTarget(), PostProcessing.compoundType.ADD);

				loadCallback();
			});
		});
		
		SceneManager.addEventListener("mousedown", mouseDownEvent);
		SceneManager.addEventListener("wheel", scrollEvent);
		SceneManager.addEventListener("mousemove", mouseMoveEvent);
		SceneManager.addEventListener("mouseup", mouseUpEvent);
	});
}

function loadCallback()
{
	var primitives = SceneManager.getTransformPrimitiveMap("Sponza");
	var html = "<ul class='list'>";
	for(var i = 0; i < primitives.length; i++){
		var primitive = primitives[i];
		var foo = primitive.split("|");
		foo.pop();
		var primitiveName = foo.join();
		html += "<li id='"+primitive+"'><input type='checkbox' value='" + primitive + "' />"; 
		html += primitiveName + "</li>";
	}
	html += "</ul>";
	$("#primitives").html(html);
	
	//实现shift选取
	$("#primitives").shiftcheckbox(function(){
		removeHighlight();
		updatePrimitiveNow();
		addHighlight();
	});
	
	$("#primitives li").hover(function(){
		$(this).addClass("hover");
	}, function(){
		$(this).removeClass("hover");
	})
	
	showEditLightPanel();
	
	$("#ssao").find("input").change(function(){
		DeferredShading.updateSSAO(this.name, this.value);
	})
}

function updateView()
{
	$("#primitives input[type=checkbox]").each(function(){
		if(!isset(primitiveNow[$(this).val()])){
			SceneManager.getPrimitive($(this).val()).owner = null;
		}
		else{
			var shapeName = SceneManager.getPrimitiveShapeMap($(this).val());
			SceneManager.getPrimitive($(this).val()).owner = SceneManager.getShape(shapeName);
		}
	})
}

function chooseAll(elem)
{
	$(elem).find("input[type=checkbox]").attr("checked", true);
	updatePrimitiveNow();
}

function chooseNone(elem)
{
	$(elem).find("input[type=checkbox]").attr("checked", false);
	updatePrimitiveNow();
}

function antiChoose(elem)
{
	$(elem).find("input[type=checkbox]").each(function(){
		this.checked = !this.checked;
	})
	updatePrimitiveNow()
}

function updatePrimitiveNow()
{
	$("#primitives input[type=checkbox]").each(function(){
		if(this.checked){
			var li = $(this).parent("li");
			li.addClass("chosen");
			primitiveNow[li.attr("id")] = (SceneManager.getPrimitive(li.attr("id")));
		}
		else{
			$(this).parent("li").removeClass("chosen");
		}
	});
}

function updatePrimitivePanel()
{
	for(var primitiveName in primitiveNow){
		$("#primitives input[type=checkbox]").each(function(){
			var li = $(this).parent("li");
			if(li.attr("id") == primitiveName){
				$(this).attr("checked", true);
				li.addClass("chosen");
			}else{
				$(this).attr("checked", false);
				li.removeClass("chosen");
			}
		})
	}
}

function addHighlight()
{
	for(var primitiveName in primitiveNow){
		var materialName = primitiveNow[primitiveName].material.name;
		if(materialName == getMaterialNameFromHighlight(materialName)){
			materialHighlightName = materialName + "_highlight";
			primitiveNow[primitiveName].material = MaterialManager.getMaterial(materialHighlightName);
		}
	}
}

function removeHighlight()
{
	for(var primitiveName in primitiveNow){
		var materialName = primitiveNow[primitiveName].material.name;
		if(materialName != getMaterialNameFromHighlight(materialName)){
			materialName = getMaterialNameFromHighlight(materialName);
			primitiveNow[primitiveName].material = MaterialManager.getMaterial(materialName);
		}
	}
	//clear the primitveNow array
	primitiveNow = [];
}

function getMaterialNameFromHighlight(materialHighlightName)
{
	var nameArray = materialHighlightName.split("_");
	if(nameArray.pop() == "highlight"){
		var materialName = nameArray.join("_");
		return materialName;
	}
	return materialHighlightName;
}

function mouseDownEvent(e){
	if(e.button == 0){
		var shapeInfo = camera.pickShape(e.x, e.y);
		var shapeName = shapeInfo.shape.name;
		var primitives = SceneManager.getShapePrimitiveMap(shapeName);
		alert(SceneManager.getPrimitive(primitives[0]).material.name)
		//TODO: multiple choose
//		removeHighlight();
		for(var i = 0; i < primitives.length; i++){
			primitiveNow[primitives[i]] = SceneManager.getPrimitive(primitives[i]);
		}
//		addHighlight();
		updatePrimitivePanel();
		//TODO:change the primitvives to shape
		var primitive = SceneManager.getPrimitive(primitives[0]);
		html = primitive.name + "<br />";
		html += "顶点数:" + primitive.numberVertices + "<br />";
		$("#primitive_info").html(html);
	}
	if(e.button == 2){
		oldPositionX = e.x;
		oldPositionY = e.y;
		mouseDown = true;
	}
}

function mouseMoveEvent(e){
	if(mouseDown){
		var cameraInfo = camera.getCameraInfo();
		var aroundPosition = o3djs.math.copyVector(cameraInfo.target);

		var vector = o3djs.math.subVector(cameraInfo.target, cameraInfo.eye);
		var vector2 = o3djs.math.copyVector(vector);
		vector2[1] = vector2[1] + 1;
		aroundXAxis = o3djs.math.cross(vector, vector2);
		
		camera.moveEyeAround({
			aroundAxis : [0, 1, 0],
			aroundPos : aroundPosition,
			step : -(e.x - oldPositionX) / 400
		})
		camera.moveEyeAround({
			aroundAxis : aroundXAxis,
			aroundPos : aroundPosition,
			step : -(e.y - oldPositionY) / 400
		})
		oldPositionX = e.x
		oldPositionY = e.y;
		//更新deferred lighting中的信息
		DeferredShading.updateGBuffer();
	}
}

function mouseUpEvent(e){
	mouseDown = false;
}

function scrollEvent(e){
	step = e.deltaY > 0 ? 0.05 : -0.05
	camera.moveTo({
		eyeTo : camera.getCameraInfo().target,
		step : step
	})

	//更新deferred lighting中的信息
	DeferredShading.updateGBuffer();
}

function focusObject(){
	updateView();
	focus("house");
}

function focus(transformName)
{
	var boundingBox = o3djs.util.getBoundingBoxOfTree(SceneManager.getTransform(transformName));
	var math = o3djs.math;
	var target = math.lerpVector(boundingBox.minExtent, boundingBox.maxExtent, 0.5);
	//alert(math.subVector(boundingBox.maxExtent, boundingBox.minExtent));
	var vect = math.subVector(boundingBox.maxExtent, boundingBox.minExtent);
	var diag = math.length(vect);
	var eye = math.addVector(target, math.mulScalarVector(1, vect));
	
	target = math.mulScalarVector(0.02, target);
	eye = math.mulScalarVector(0.02, eye);
	
	SceneManager.appendRenderCallback("focus", function(re){
		camera.moveTo({
			eyeTo : eye,
			targetTo : target,
			step : 0.05
		})
		if(Math.abs(math.length(math.subVector(camera.getCameraInfo().eye, eye))) < 1){
			SceneManager.removeRenderCallback("focus");
		}
		//更新deferred lighting中的信息
		DeferredShading.updateGBuffer();
	})
}

function showEditLightPanel()
{
	var lights = SceneManager.getLight();
	for(var lightName in lights){
		var light = lights[lightName];
		var l = $(".light_template").clone();
		l.appendTo("#edit_light").attr("id", "light_" + lightName).
									attr("class", "light").css("display", "block");
        l.find(".light_name b").html(lightName);
		
        var propertys = {
            "position": light.getPosition(),
            "target": light.getTarget(),
            "direction": light.getDirection()
        };
		for(var propertyName in propertys){
			var input = l.find("."+propertyName+" input");
			var property = propertys[propertyName];
			if(isset(property)){
				for(var i = 0; i < input.length; i++){
					$(input[i]).val(property[i]);
					$(input[i]).attr("class", i);
				}
			}else{
				l.find("."+propertyName).css("display", "none");
			}
		}
		
		propertys = {
			"aspect" : light.getAspect(),
			"attenuation" : light.getAttenuation(),
			"power" : light.getPower()
		}
		for (var propertyName in propertys) {
			var property = propertys[propertyName];
			if (isset(property)) {
				l.find("." + propertyName + " input").val(property);
			}
			else {
				l.find("."+propertyName).css("display", "none");
			}
		}
	}
}

function updateLight()
{
	var materials = MaterialManager.getMaterial();
	for(var materialName in materials){
		if(materialName != "light_material"){
			MaterialManager.updateParam(materialName, "lightWorldPos", lightPos);
			//更新摄像机2(灯光)参数
			var camera = SceneManager.getCamera("light_camera").setCamera(lightPos, [0, 0, 0], [0, 1, 0]);
			//更新矩阵
			MaterialManager.updateParam(materialName, "lightViewProjection", o3djs.math.matrix4.composition(camera.getProjectionMatrix(), camera.getCameraMatrix()));
		}
	}
	//移动灯泡
	var light = SceneManager.getTransform("light");
	light.identity();
	light.translate(lightPos);
}

function showMaterialManager()
{
	var html = "<div class='divider2'></div>";
	html += "<b>所有材质:</b>"
	html += "<ul class='list'>";
	var materials = MaterialManager.getOption();
	for(var materialName in materials){
		if(materialName == getMaterialNameFromHighlight(materialName) ){
			html += "<li>"
			html += "<input type='text' value='" + materialName + "'>";
			html += "<label class='info'></label>";
			html += "<span></span>";
			html += "</li>";
		}
	}
	html += "</ul>";
	$("#material_manager").html ("");
	$(html).appendTo($("#material_manager")).find("li input").focus(function(){
		this.oldMaterialName = $(this).val();
	}).
	blur(function(){
		var materialName = $(this).val();
		MaterialManager.updateMaterialName(materialName, this.oldMaterialName);
		showMaterialManager();
	}).
	parent("li").click(function(){
		$(this).parent().find("li").removeClass("chosen");
		$(this).addClass("chosen");
		var materialName = $(this).find("input").val();
		materialNow = MaterialManager.getMaterial(materialName);
		showEditMaterialPanel(materialName);
	}).
	hover(function(){
		$(this).addClass("hover");
	}, function(){
		$(this).removeClass("hover");
	})
}

function showEditMaterialPanel(materialName)
{
	option = MaterialManager.getOption(materialName);
	var initHtml = "<div class='divider2'></div>"; 
	initHtml += "<b>当前材质名 ： </b>"+materialName+"<div class='divider'></div>";
	initHtml += "<b>属性 ： </b><br />"
	$("#edit_material").html(initHtml);
	
	for(var variableName in option.Variable){
		var variable = option.Variable[variableName];
		switch(variable.UIWidget){
		case "color_picker":
			createColorPicker(variableName, variable, $("#edit_material"));
			break;
		case "slider":
			createSlider(variableName, variable, $("#edit_material"));
			break;
		}
	}
	if(isset(option.Texture)){
		for(var textureName in option.Texture){
			var texture = option.Texture[textureName];
			if(texture.src){
				createToggleTexture(textureName, texture, "#edit_material");
			}
		}
	}
}


function createColorPicker(name, option, parent)
{
	html = "<div class='" + name + "'>";
	html += option.UIName + " : ";
	html += "<input type='text' class='color' value='"+ hslToHex(option.defaultValue) +"'/>";
	html += "<div class='divider'></div>";
	html += "</div>";
	
	parent.append(html);
	$("#edit_material ." + name + " .color").focus(function(){
		if($(".color_picker").length > 0){
			$(".color_picker").remove();
		}
		var pos = $(this).offset();
		$("<div class='color_picker'></div>").appendTo(document.body).css({
			"left": pos.left,
			"top": pos.top + 20,
			"position":"absolute"
		}).
		farbtastic(function(color){
			MaterialManager.updateParam(getMaterialNameFromHighlight(materialNow.name), name, HexToHsl(color));
		})
	}).blur(function(){
		$(".color_picker").remove();
	})
}

function createSlider(name, option, parent)
{
	html = "<div class='" + name + "'>";
	html += option.UIName + " : ";
	html += "<div class='slider'></div>";
	html += "<div class='divider'></div>"
	html += "</div>";
	
	$(html).appendTo(parent).find(".slider").slider({
			orientation: 'horizontal',
			range: "min",
			min : option.UIMin,
			max: option.UIMax,
			step : option.UIStep,
			value: option.defaultValue,
			slide: function(event, ui){
				var value = ui.value;
				var materialName = materialNow.name
				MaterialManager.updateParam(getMaterialNameFromHighlight(materialName), name, value);
				if(name == "opacity"){
					MaterialManager.bindCamera(materialName, "main_camera", true);
				}
			},
		});
}

function createToggleTexture(name, option, parent)
{
	html = "<div class='" + name + "'>";
	html += option.UIName + " : ";
	html += "<img src = '" + option.src + "' width='100px' height='100px'><br /><br />";
	html += "上传新的纹理:<input type='file' class='uploader'/>";
	html += "<div class='divider'></div>";
	html += "</div>";
	
	$(html).appendTo(parent).find(".uploader").uploadify({
		"uploader" : "lib/uploadify/uploadify.swf",
		"script" : "action/uploadTexture.php",
		"auto" : true,
		"cancelImg" : "lib/uploadify/cancel.png",
		"onComplete" : function(event, queueID, fileObj, response, data){
		}
	})
}

function showMaterialTemplate()
{
	$.post("action/getFxList.php", {}, function(json){
		var fxFiles = eval("(" + json + ")");
		html = "<ul class='list'>"
		for(var name in fxFiles){
			html += "<li id='" + name + "'>" + fxFiles[name] + "</li>";
		}
		html += "</ul>";
		
		$("#add_material").append(html).find("li")
		.hover(function(){
			$(this).addClass("hover");
		}, function(){
			$(this).removeClass("hover");
		})
		.click(function(){
			var material = MaterialManager.getMaterial(this.id);
			var name = this.id;
			if(!isset(material)){
				MaterialManager.loadFxFile(name, $(this).html(), function(material){
					MaterialManager.bindCamera(name, "main_camera");
					materialNow = material;
					showEditMaterialPanel(name);
					showMaterialManager();
				})
			}
			else{
				materialNow = material;
				showEditMaterialPanel(name);
				showMaterialManager();
			}
			showMaterialManager();
		})
	})
	
	$("<div id='add_material'></div>").dialog({
        "position": 'right',
        "draggable": false,
		"show" : "fold",
		"hide" : "fold",
		"width" : 300,
		"title" : "添加材质",
		"draggable" : true,
        "close": function(){
			$("#add_material").remove();
        }
    });
}

function addMaterialToPrimitives()
{
	if(materialNow){
		if(primitiveNow){
			for(var primitiveName in primitiveNow){
				primitiveNow[primitiveName].material = materialNow;
			}
		}else{
			error("请选择物体")
		}
	}else{
		error("请选择材质");
	}
}

function HexToHsl(hex)
{
	hsl = [];
	hsl[0] = parseInt(hex.substring(1,3), 16)/255;
	hsl[1] = parseInt(hex.substring(3,5), 16)/255;
	hsl[2] = parseInt(hex.substring(5,7), 16)/255;
	return hsl;
}

function hslToHex(hsl)
{
	return "#" + parseInt(hsl[0]*255).toString(16) + parseInt(hsl[1]*255).toString(16) + parseInt(hsl[2]*255).toString(16);
}

function createMaterialCopy(){
	var materialName = materialNow.name;
	MaterialManager.copyMaterial(materialName + "_copy", materialName);
	//同时复制该材质选种高亮后的材质
	MaterialManager.copyMaterial(materialName + "_copy", materialName + "_highlight");
	//刷新材质管理面板
	showMaterialManager();
}
